﻿using System.Collections.Generic;
using UnityEngine;
using ZYLFramework.Common;

namespace ZYLFramework.Manage
{
    class TimerNode : IReference
    {
        public TimerManage.TimerHandler Callback;
        public float RepeatRate; // 定时器触发的时间间隔;
        public float Time; // 第一次触发要隔多少时间;
        public int Repeat; // 你要触发的次数;
        public float PassedTime; // 这个Timer过去的时间;
        public bool IsRemoved; // 是否已经删除了
        public int TimerId; // 标识这个timer的唯一Id号;
        
        /// <summary>
        /// 对象池回收方法 
        /// </summary> 
        public void Clear()
        {
            Callback = null;
            Repeat = 1;
            RepeatRate = 0;
            Time = 1000;
            PassedTime = 0;
            IsRemoved = false;
            TimerId = 99999;
        }

        public void Init(TimerManage.TimerHandler methodName, int repeat, float repeatRate, float time, int autoIncId)
        {
            Callback = methodName;
            Repeat = repeat;
            RepeatRate = repeatRate;
            Time = time;
            PassedTime = repeatRate; // 延迟调用
            IsRemoved = false;
            TimerId = autoIncId;
        }
    }

    public class TimerManage:MonoSingleton<TimerManage>
    {
       public delegate void TimerHandler();
        private Dictionary<int, TimerNode> _timers = null;//存放Timer对象
    
        private List<TimerNode> _removeTimers = null;//新增Timer缓存队列
        private List<TimerNode> _newAddTimers = null;//删除Timer缓存队列
    
        private int _autoIncId = 1;//每个Timer的唯一标示
    
        //初始化Timer管理器
        protected override void Awake()
        {
            base.Awake();
            _timers = new Dictionary<int, TimerNode>();
            _autoIncId = 1;
            _removeTimers = new List<TimerNode>();
            _newAddTimers = new List<TimerNode>();
        }
    
        /// <summary>
        /// 以秒为单位调用方法methodName，然后在每个repeatRate重复调用。
        /// </summary>
        /// <param name="methodName">回调函数</param>
        /// <param name="time">延迟调用</param>
        /// <param name="repeatRate">时间间隔</param>
        /// <param name="repeat">重复调用的次数 小于等于0表示无限触发</param>
        public int Schedule(TimerHandler methodName, float time, float repeatRate, int repeat=0)
        {
            TimerNode timer = ObjectPoolManager.Instance.GetObject<TimerNode>();
            timer.Init(methodName, repeat, repeatRate, time, _autoIncId);
            _autoIncId++;
            _newAddTimers.Add(timer); // 加到缓存队列里面
            return timer.TimerId;
        }
    
        //移除Timers
        public void Unschedule(int timerId)
        {
            if (!_timers.ContainsKey(timerId))
            {
                return;
            }
            TimerNode timer = _timers[timerId];
            timer.IsRemoved = true; // 先标记，不直接删除
        }
    
        //在Update里面调用
        void Update()
        {
            float dt = Time.deltaTime;
            // 添加新的Timers
            for (int i = 0; i < _newAddTimers.Count; i++)
            {
                _timers.Add(_newAddTimers[i].TimerId, _newAddTimers[i]);
            }
            _newAddTimers.Clear();
            foreach (TimerNode timer in _timers.Values)
            {
                if (timer.IsRemoved)
                {
                    _removeTimers.Add(timer);
                    continue;
                }
                timer.PassedTime += dt;
                if (timer.PassedTime >= (timer.Time + timer.RepeatRate))
                {
                    // 做一次触发
                    timer.Callback();
                    timer.Repeat--;
                    timer.PassedTime -= (timer.Time + timer.RepeatRate);
                    timer.Time = 0; 
                    if (timer.Repeat == 0)
                    {
                        // 触发次数结束，将该删除的加入队列
                        timer.IsRemoved = true;
                        _removeTimers.Add(timer);
                    }
                }
            }
            // 清理掉要删除的Timer;
            for (int i = 0; i < _removeTimers.Count; i++)
            {
                _timers.Remove(_removeTimers[i].TimerId);
                ObjectPoolManager.Instance.Recycle(_removeTimers[i]);
            }
            _removeTimers.Clear();
        }

        private void OnDestroy()
        {
            _newAddTimers.Clear();
        }
    }
}